# Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 2.0, or
# GNU General Public License version 2, or
# GNU Lesser General Public License version 2.1.

abort "this file should be run on TruffleRuby to list TruffleRuby's Array methods" unless RUBY_ENGINE == 'truffleruby'

copyright = File.read(__FILE__)[/Copyright \(c\) \d+, \d+ Oracle/]
file = 'src/main/ruby/truffleruby/core/truffle/versioned_array.rb'

code = <<RUBY
# frozen_string_literal: true

# #{copyright} and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 2.0, or
# GNU General Public License version 2, or
# GNU Lesser General Public License version 2.1.

# GENERATED BY #{__FILE__}

# This class is used for $LOADED_FEATURES and $LOAD_PATH.

class Truffle::VersionedArray < Array
  # the monitor must be owned when calling this method
  attr_reader :version

  def initialize(lock)
    @lock = lock
    @version = 0
  end

RUBY

mutating_methods_name =
  [:<<, :[]=, :append, :clear, :collect!, :compact!, :concat, :delete, :delete_at, :delete_if, :fill, :filter!,
   :flatten!, :insert, :keep_if, :map!, :pop, :prepend, :push, :reject!, :replace, :reverse!, :rotate!, :select!,
   :shift, :shuffle!, :slice!, :sort!, :sort_by!, :uniq!, :unshift]

mutating_methods, read_only_methods = Array.public_instance_methods(false).partition do |method|
  mutating_methods_name.include? method
end

read_only_methods.concat Enumerable.public_instance_methods(false)

mutating_methods.sort.each do |method|
  code << <<-RUBY
  def #{method}(*args, &block)
    TruffleRuby.synchronized(@lock) { @version += 1; super(*args, &block) }
  end

  RUBY
end

read_only_methods.uniq.sort.each do |method|
  code << <<-RUBY
  def #{method}(*args, &block)
    copy = TruffleRuby.synchronized(@lock) { Array.new self }
    copy.#{method}(*args, &block)
  end

  RUBY
end

code << "end\n"

File.write(file, code)
